﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Collections;
using System.Drawing;
using System.Web.UI.HtmlControls;

namespace ImageTable
{
    [Serializable]
    public class ImageTable : CompositeControl
    {
       
        [Bindable(true)]
        [Localizable(true)]

        private int _numberofpages;
        private List<string> _urls;
        private List<string> _selectedurls;
        private List<string> _page;
        private Color _cellColor = System.Drawing.ColorTranslator.FromHtml("#F1F1F1"); //default
        private Color _selectionColor = Color.DarkBlue; //default
        private string _albumsFolder = "Albums";

        private string _pagesNumberKey = "PagesNumber";
        private string _selectedUrlsKey = "SelectedUrls";
        private string _lowBorderKey = "LowBorder";
        private string _onPageKey = "OnPage";
        private string _selectedImgUrlKey = "SelectedImageUrl";
        private string _selectedImgNumberKey = "SelectedImageNumber";
        private string _urlsKey = "Urls";

        private static readonly object EventSubmitKey =  new object();

        protected override System.Web.UI.HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }


        public int NumberOfPages
        {
            get 
            {
                if (ViewState[_pagesNumberKey] != null)
                    return (int)ViewState[_pagesNumberKey];
                else return 0;
            }
        }
        public List<string> SelectedUrls
        { 
            
            get 
            {
                if (ViewState[_selectedUrlsKey] != null)
                {
                    List<string> selectedUrls = new List<string>();
                    foreach (string url in (List<string>)ViewState[_selectedUrlsKey])
                        selectedUrls.Add(ResolveUrl(url));
                    return selectedUrls;
                }
                else return null;
            } 
        }

        public int CurrentPage
        {
            set
            {
                if ((value > 0) && (value <= _numberofpages))
                {
                    ViewState[_lowBorderKey] = (value - 1) * ImagesPerPage;
                    ClearSelection();
                    CreateChildControls();
                }
            }
            get
            {
                if (ViewState[_onPageKey] != null && ViewState[_lowBorderKey] != null)
                {
                    int photosPerPage = (int)ViewState[_onPageKey];
                    int lowborder = (int)ViewState[_lowBorderKey];
                    return lowborder / photosPerPage + 1;
                }
                else return 0;
            }

        }
        public int ImagesPerPage
        {
            get
            {
                if (ViewState[_onPageKey] != null)
                    return (int)ViewState[_onPageKey];
                else return 0;
            }
            set
            {
                if (value > _urls.Count)
                {
                    ViewState[_onPageKey] = _urls.Count;
                }
                else ViewState[_onPageKey] = value;
                ClearSelection();
                ViewState[_lowBorderKey] = 0;
                CreateChildControls();
            }
        }

        public string SelectedImageUrl
        {
            get 
            {
                if (ViewState[_selectedImgUrlKey] != null)
                {
                    return ResolveUrl((string)ViewState[_selectedImgUrlKey]);
                }
                else return "";
            }
        }
        public int SelectedImageNumber
        {
            get
            {
                if (ViewState[_selectedImgNumberKey] != null)
                    return (int)ViewState[_selectedImgNumberKey];
                else return 0;
            }
        }

        public void LoadParameters(List<string> pathes, int pagenumber, int btnsonpage)
        {
            int lowborder = (pagenumber - 1) * btnsonpage;
            ViewState[_urlsKey] = pathes;
            ViewState[_lowBorderKey] = lowborder;
            ViewState[_onPageKey] = btnsonpage;
            if (lowborder + btnsonpage > pathes.Count)
            {
                btnsonpage = pathes.Count - lowborder;
                ViewState[_onPageKey] = btnsonpage;
            }
            ClearSelection();
            CreateChildControls();
        }
        public void LoadParameters(List<string> pathes)
        {
            LoadParameters(pathes, 1, pathes.Count);
        }
        private void ClearSelection()
        {
           ViewState[_selectedImgNumberKey] = null;
           ViewState[_selectedImgUrlKey] = null;
           ViewState[_selectedUrlsKey] = null;
        }
        
        protected override void CreateChildControls()
        {
            Controls.Clear();            
            if (ViewState[_urlsKey] != null)
            {                
                LoadControl();
            }
            base.CreateChildControls();
            OnPictureChanged(EventArgs.Empty);
        }

        private void LoadControl()
        {
            _selectedurls = new List<string>();
            _urls = (List<string>)ViewState[_urlsKey];
            CalculatePages();
            SetDefaults();
            GenerateImages();
        }
        private void CalculatePages()
        {
            int photosPerPage = (int)ViewState[_onPageKey];
            _numberofpages = _urls.Count / photosPerPage;
            if (_urls.Count % photosPerPage != 0)
                _numberofpages++;
            ViewState[_pagesNumberKey] = _numberofpages;
        }
        private void SetDefaults()
        {
            if (ViewState[_selectedImgNumberKey] == null)
                ViewState[_selectedImgNumberKey] = ViewState[_lowBorderKey];

            if (ViewState[_selectedImgUrlKey] == null)
                UrlToViewState();
        }
        private void UrlToViewState()
        {
            string url = _urls[(int)ViewState[_selectedImgNumberKey]];
            string apppath = url.Substring(0, url.IndexOf(_albumsFolder));
            url = ResolveUrl(url.Replace(apppath, "~/"));
            ViewState[_selectedImgUrlKey] = url;
        }

        private void GenerateImages()
        {
            int lowborder=(int)ViewState[_lowBorderKey];
            int btnsonpage = (int)ViewState[_onPageKey];
            _page = new List<string>();

            if (lowborder + btnsonpage > _urls.Count)
            {
                btnsonpage = _urls.Count - lowborder;
            }
            int highborder=lowborder+btnsonpage;
            for (int i = lowborder; i < highborder; i++)
                _page.Add(_urls[i]);

            List<ImageButton> imageFileList = TurnImagesIntoButtons(_page);

            GenerateImageView(imageFileList);
            foreach (ImageButton imgbtn in imageFileList)
                imgbtn.Click += new ImageClickEventHandler(this.OnImageButtonClick);
        }
        private List<ImageButton> TurnImagesIntoButtons(List<string> page)
        {
            //Так как нельзя присваивать ширину и высоту контрола какой-то переменной, 
            //то для этого создаются Bitmap-ы
            List<ImageButton> imageFileList = new List<ImageButton>();
            int counterID = 0;

            foreach (string strFileName in page)
            {
                counterID++;
                using (Bitmap img = new Bitmap(strFileName))
                {
                    string apppath = strFileName.Substring(0, strFileName.IndexOf(_albumsFolder));
                    imageFileList.Add(new ImageButton
                    {
                        ID = "" + counterID,
                        ImageUrl = ResolveUrl(strFileName.Replace(apppath, "~/")),
                        Visible = true,
                        Width = img.Width,
                        Height = img.Height
                    });
                }
            }
            return imageFileList;
        }
        private Bitmap Resize(Bitmap img)
        {
            int width = 150;
            int height = 150;
            float k = 0f;
            float kWidth = 0f;
            float kHeight = 0f;
            kWidth = width / Convert.ToSingle(img.Width);
            kHeight = height / Convert.ToSingle(img.Height);
            if (kWidth < kHeight)
            {
                k = kWidth;
                height = Convert.ToInt32(img.Height * k);
            }
            else
            {
                k = kHeight;
                width = Convert.ToInt32(img.Width * k);
            }
            Bitmap newBitmap = new Bitmap(width, height);
            return newBitmap;
        }

        private void GenerateImageView(List<ImageButton> imageFileList)
        {
            HtmlGenericControl divImageRow;
            int idcounter = 0;
            foreach (ImageButton imgb in imageFileList)
            {
                divImageRow = new HtmlGenericControl("div");
                divImageRow.Attributes.Add("class", "albumimage");
                divImageRow.Controls.Add(imgb);
                divImageRow.Controls.Add(new LiteralControl("<br />"));
                CheckBox check = new CheckBox();
                check.CheckedChanged += CheckBoxChanged;
                check.ID = "chkbox" + idcounter;
                divImageRow.Controls.Add(check);
                idcounter++;
                Controls.Add(divImageRow);
            }
        }

        private void OnImageButtonClick(object sender, ImageClickEventArgs e)
        {
            int lowborder = (int)ViewState[_lowBorderKey];
            ViewState[_selectedImgUrlKey] = ((ImageButton)sender).ImageUrl;
            ViewState[_selectedImgNumberKey] = int.Parse(((ImageButton)sender).ID) - 1 + lowborder;
            OnPictureChanged(EventArgs.Empty);
        }
        private void CheckBoxChanged(object sender, EventArgs e)
        {
            if (ViewState[_selectedUrlsKey] != null)
                _selectedurls = (List<string>)ViewState[_selectedUrlsKey];
            else _selectedurls = new List<string>();
           string checkboxId = ((CheckBox)sender).ID.Substring(6);
            //Checkbox has ID "chkbox<number>", number starts from 6th symbol
           int imgNumber=int.Parse(checkboxId);
           if (((CheckBox)sender).Checked == true)
               _selectedurls.Add(_page[imgNumber]);
           else _selectedurls.Remove(_page[imgNumber]);
           ViewState[_selectedUrlsKey] = _selectedurls;
        }
        public void SelectNextImage()
        {
            int lowborder = (int)ViewState[_lowBorderKey];
            int highborder = lowborder + (int)ViewState[_onPageKey] - 1;
            int selectedimgnumber = (int)ViewState[_selectedImgNumberKey];
            if (selectedimgnumber == _urls.Count-1)
            {
                ViewState[_lowBorderKey] = 0;
                ClearSelection();
                CreateChildControls();
            }
            else
            if (selectedimgnumber == highborder)
            {
                ViewState[_lowBorderKey] = highborder + 1;
                ClearSelection();
                CreateChildControls();
            }
            else
            {
                selectedimgnumber++;
                ViewState[_selectedImgNumberKey] = selectedimgnumber;
                UrlToViewState();
                OnPictureChanged(EventArgs.Empty);
            }
        }

        public void SelectPreviousImage()
        {
            int lowborder = (int)ViewState[_lowBorderKey];
            int highborder = lowborder + (int)ViewState[_onPageKey] - 1;
            int selectedimgnumber = (int)ViewState[_selectedImgNumberKey];
            if (selectedimgnumber == 0)
            {
                ClearSelection();
                ViewState[_selectedImgNumberKey] = _urls.Count - 1;
                ViewState[_lowBorderKey] = (_numberofpages - 1) * (int)ViewState[_onPageKey];
                CreateChildControls();
            }
            else
            if (selectedimgnumber == lowborder)
            {
                ClearSelection();
                ViewState[_selectedImgNumberKey] = selectedimgnumber - 1;
                ViewState[_lowBorderKey] = lowborder - (int)ViewState[_onPageKey];
                CreateChildControls();
            }
            else
            {
                selectedimgnumber--;
                ViewState[_selectedImgNumberKey] = selectedimgnumber;
                UrlToViewState();
                OnPictureChanged(EventArgs.Empty);
            }

        }
        public void Clear()
        {
            ClearSelection();
            ViewState[_urlsKey] = null;
            ViewState[_lowBorderKey] = null;
            ViewState[_onPageKey] = null;
            CreateChildControls();
        }
       
        [Category("Action"),
       Description("Raised when the user clicks the imagebutton.")]
        public event EventHandler PictureChanged
        {
            add
            {
                Events.AddHandler(EventSubmitKey, value);
            }
            remove
            {
                Events.RemoveHandler(EventSubmitKey, value);
            }
        }

        // The method that raises the PictureChanged event.
        protected virtual void OnPictureChanged(EventArgs e)
        {
            EventHandler PictureChangedHandler =
                (EventHandler)Events[EventSubmitKey];
            if (PictureChangedHandler != null)
            {
                PictureChangedHandler(this, e);
            }
        }

    }   
}
